﻿using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;

namespace DimensionsHelper.LanguageService.Syntax;

public class IfStatement : BodiedStatement
{
    private readonly SyntaxToken _keywordToken;
    private Expression? _conditionExpression;


    private IfStatement? _elseBranch;


    private SyntaxToken? _thenKeywordToken;

    internal IfStatement(SyntaxToken keywordToken, SyntaxNode? parent) :
        base(SyntaxKinds.IfStatement, parent)
    {
        SetChildField(ref _keywordToken, keywordToken);
    }


    public SyntaxToken KeywordToken => _keywordToken;

    public SyntaxToken? ThenKeywordToken => _thenKeywordToken;


    /// <summary>
    ///     条件语句
    /// </summary>
    public Expression? ConditionExpression => _conditionExpression;


    /// <summary>
    ///     如果条件语句不是空，返回<see langword="true" />，表示此条件语句是 if 或 elseif 语句。
    ///     否则，表示此语句为 else 语句。
    /// </summary>
    [MemberNotNullWhen(true, nameof(ConditionExpression))]
    public bool HasCondition => !Expression.IsEmptyExpression(ConditionExpression);

    /// <summary>
    ///     后续的 else 或 elseif 语句
    /// </summary>
    public IfStatement? ElseBranch => _elseBranch;

    /// <summary>
    ///     前一个 if 分支
    /// </summary>
    public IfStatement? PreviousBranch { get; private set; }


    public bool IsSingleLineStatement
    {
        get
        {
            if (PreviousBranch == null && /* 只有在起始的If语句中才可能返回true */ Body.Statements.Count == 1 &&
                Body.Statements[0]
                    .IsOneOfNode(SyntaxKinds.ExpressionStatement, SyntaxKinds.ExitStatement) /* Exit 允许不换行 */)
            {
                // If ... Then ...
                if (ElseBranch == null)
                {
                    return true;
                }

                // If ... Then ... Else ...
                if (!ElseBranch.HasCondition &&
                    ElseBranch.Body.Statements.Count == 1 &&
                    ElseBranch.Body.Statements[0]
                        .IsOneOfNode(SyntaxKinds.ExpressionStatement, SyntaxKinds.ExitStatement))
                {
                    return true;
                }
            }

            return false;
        }
    }


    public void Update(Expression conditionExpression, SyntaxToken thenKeywordToken)
    {
        Debug.Assert(SyntaxToken.IsNullOrEmpty(thenKeywordToken) ||
                     thenKeywordToken.IsNode(SyntaxKinds.ThenKeywordToken));
        SetChildNullableField(ref _conditionExpression, Expression.IsEmptyExpression, conditionExpression);
        SetChildNullableField(ref _thenKeywordToken, SyntaxToken.IsNullOrEmpty, thenKeywordToken);
    }


    public void Update(IfStatement elseBranch)
    {
        if (_elseBranch != null)
        {
            _elseBranch.PreviousBranch = null;
        }

        elseBranch.PreviousBranch = this;
        SetChildNullableField(ref _elseBranch, elseBranch);
    }


    public override void AcceptVisitor<T>(SyntaxNodeVisitor<T> visitor)
    {
        Accept(visitor, KeywordToken, ConditionExpression, ThenKeywordToken);
        Accept(visitor, ElseBranch);
        base.AcceptVisitor(visitor);
    }
}


public static partial class NodeFactory
{
    public static IfStatement CreateIfStatement(SyntaxNode? parent, SyntaxToken keywordToken, Expression? condition,
        SyntaxToken? thenKeywordToken)
    {
        Debug.Assert(keywordToken.IsOneOfNode(SyntaxKinds.IfKeywordToken, SyntaxKinds.ElseIfKeywordToken,
            SyntaxKinds.ElseKeywordToken));
        Debug.Assert((condition == null && thenKeywordToken == null) ||
                     (condition != null &&
                      (SyntaxToken.IsNullOrEmpty(thenKeywordToken) ||
                       thenKeywordToken.IsNode(SyntaxKinds.ThenKeywordToken))));
        IfStatement stat = new(keywordToken, parent);
        if (condition != null && thenKeywordToken != null)
        {
            stat.Update(condition, thenKeywordToken);
        }

        return stat;
    }
}